package cn.gok.springsecuritydemo02.config;

import cn.gok.springsecuritydemo02.filter.ValidateCodeFilter;
import cn.gok.springsecuritydemo02.handler.LoginFailHandler;
import cn.gok.springsecuritydemo02.handler.LoginSuccessHandler;
import cn.gok.springsecuritydemo02.handler.SessionInformationExpiredHandler;
import cn.gok.springsecuritydemo02.serivce.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import javax.sql.DataSource;

/**
 * @author: chen fan
 * @since: 2022/11/21 10:34
 * @description:
 */
@Configuration
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    MyUserDetailsService userDetailsService;

    @Autowired
    ValidateCodeFilter validateCodeFilter;

    @Autowired
    LoginSuccessHandler successHandler;

    @Autowired
    LoginFailHandler failHandler;


    @Autowired
    SessionInformationExpiredHandler sessionInformationExpiredHandler;





    /**
     * 重写此方法进行自定义的验证配置
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        /*
            将自定义的验证码的过滤器添加到 UsernamePasswordAuthenticationFilter 之前

            addFilter() 将过滤器添加在末尾
            addFilterBefore(自定义过滤器, 其它过滤器.class)  将当前定义过滤器添加在指定过滤器之前
            addFilterAfter(自定义过滤器, 其它过滤器.class)
         */
        http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class);


        //添加跨域配置
        http.cors().configurationSource(corsConfigurationSource());


        http
                //开启表单验证
                .formLogin()
                //指定登录页
                .loginPage("/toLoginPage")
                .loginProcessingUrl("/login")
                .successHandler(successHandler)
                .failureHandler(failHandler)
                .and()
                // 获取授权管理控制对象， Security所有的权限控制都基于这个类进行控制。
                .authorizeRequests()
                //login.html 被放过，不需要做验证， 需要注意： 放过的请求配置 一定要处于 所有请求都必须验证配置的最的上面
                .antMatchers("/toLoginPage","/user/addUser","/addUser.html","/user/getValidateCode").permitAll()
                //所有的请求
                .anyRequest()
                //进行验证
                .authenticated()
                .and()
                //获取Session管理器
                .sessionManagement()
//                //设置session失效后的跳转地址
                .invalidSessionUrl("/toLoginPage")
                //设置session最大会话数量 ,1同一时间只能有一个用户登录
                .maximumSessions(1)
                //当达到最大会话个数时阻止登录。
                .maxSessionsPreventsLogin(true)
                //session过期后跳转地址
                .expiredUrl("/toLoginPage");
                //添加自定义的session失效后的处理器
//                .expiredSessionStrategy(sessionInformationExpiredHandler);




        // 关闭csrf防护
        http.csrf().disable();

        // 允许iframe加载页面
        http.headers().frameOptions().sameOrigin();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 使用自定义的UserDetailsService  从数据库获取用户信息
        auth.userDetailsService(userDetailsService);
    }


    @Override
    public void configure(WebSecurity web) throws Exception {
        //放过静态资源
        web.ignoring().antMatchers("/css/**","/js/**","/images/**","/temp/validateCode/**");
    }

    /**
     * 添加跨域配置对象
     * @return
     */
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        // 设置允许跨域的站点，不能设置为 *
        corsConfiguration.addAllowedOrigin("http://127.0.0.1:8848");
        // 设置允许跨域的http方法
        corsConfiguration.addAllowedMethod("*");
        // 设置允许跨域的请求头
        corsConfiguration.addAllowedHeader("*");
        // 允许带凭证
        corsConfiguration.setAllowCredentials(true);

        // 对所有的url生效
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration);
        return source;
    }

}
